package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.domain.ProdTagReference;
import cn.com.dcsgo.domain.Sku;
import cn.com.dcsgo.dto.*;
import cn.com.dcsgo.exception.BusinessException;
import cn.com.dcsgo.mapper.ProdTagReferenceMapper;
import cn.com.dcsgo.mapper.SkuMapper;
import cn.com.dcsgo.utils.AuthUtil;
import cn.com.dcsgo.vo.DeliveryModeVO;
import cn.com.dcsgo.vo.ProdVO;
import cn.com.dcsgo.vo.SkuVO;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.com.dcsgo.domain.Prod;
import cn.com.dcsgo.service.ProdService;
import cn.com.dcsgo.mapper.ProdMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 针对表【prod(商品表)】的数据库操作Service实现
 *
 * @author Dcsgo
 * @since 2025-10-14 08:45:29
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "cn.com.dcsgo.service.impl.ProdServiceImpl")
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod>
        implements ProdService {
    @Resource
    private ProdTagReferenceMapper prodTagReferenceMapper;

    @Resource
    private SkuMapper skuMapper;

    @Override
    public Page<Prod> getPage(PageDTO pageDTO, ProdQueryDTO prodQueryDTO) {
        // 用户只能查询自己店铺下的商品，超级店铺下的用户可以查看所有商品信息
        Long shopId = AuthUtil.getShopId();
        String prodName = prodQueryDTO.getProdName();
        Integer status = prodQueryDTO.getStatus();
        Page<Prod> page = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
        return baseMapper.selectPage(page,
                new LambdaQueryWrapper<Prod>()
                        // shopID目前可能为空
                        .eq(shopId == null || !shopId.equals(1L), Prod::getShopId, shopId)
                        .eq(status != null, Prod::getStatus, status)
                        .like(StringUtils.hasText(prodName), Prod::getProdName, prodName)
        );
    }

    @Override
    public boolean logicalRemoveBatchByIds(List<Long> prodIds) {
        int row = 0;
        if (!CollectionUtils.isEmpty(prodIds)) {
            row += baseMapper.updateStatusByIds(prodIds, -1);
            for (Long prodId : prodIds) {
                removeCache(prodId);
            }
        }
        log.debug("ProdServiceImpl:52:logicalRemoveBatchByIds,row:{}", row);
        return row > 0;
    }

    /**
     * 清除缓存中的商品信息
     *
     * @param prodId 商品ID
     */
    @CacheEvict(key = "#prodId")
    public void removeCache(Long prodId) {
        // 空方法，只用于清除缓存
    }

    public boolean existsProdName(long shopId, String prodName) {
        return baseMapper.exists(
                new LambdaQueryWrapper<Prod>()
                        .eq(Prod::getShopId, shopId)
                        .eq(Prod::getProdName, prodName)
        );
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean save(ProdAddDTO prodAddDTO) {
        Long shopId = AuthUtil.getShopId();
        if (shopId == null) {
            throw new BusinessException("请先关联店铺后操作");
        }
        // 1. 同店铺下的商品名不能重复
        if (existsProdName(shopId, prodAddDTO.getProdName())) {
            throw new BusinessException("商品【" + prodAddDTO.getProdName() + "】已存在");
        }
        // 2. 向商品表中添加数据
        Prod prod = new Prod();
        BeanUtil.copyProperties(prodAddDTO, prod);
        prod.setShopId(shopId);
        prod.setSoldNum(0);
        log.debug("prodAddDTO.getDeliveryModeVO():{}", prodAddDTO.getDeliveryModeVo());
        prod.setDeliveryMode(JSON.toJSONString(prodAddDTO.getDeliveryModeVo()));
        log.debug("prod.setDeliveryMode():{}", prod.getDeliveryMode());
        prod.setCreateTime(new Date());
        if (prodAddDTO.getStatus().equals(1)) {
            prod.setPutawayTime(new Date());
        }
        prod.setVersion(0);
        int row = 0;
        row += baseMapper.insert(prod);

        // 3. 商品关联了活动，向商品活动关联表中添加数据
        if (!CollectionUtils.isEmpty(prodAddDTO.getTagList())) {
            row += prodTagReferenceMapper.batchInsert(shopId, prodAddDTO.getTagList(), prod.getProdId(), 1, new Date());
        }

        // 4. 商品有关联的SKU，向SKU表中添加数据
        if (!CollectionUtils.isEmpty(prodAddDTO.getSkuList())) {
            row += skuMapper.batchInsert(prod.getProdId(), prodAddDTO.getSkuList());
        }

        // TODO：5. 配送相关

        log.debug("112:ProdServiceImpl.save():row:{}", row);
        return row > 0;
    }

    @Override
    public ProdVO getProdVOById(Long prodId) {
        Prod prod = baseMapper.selectById(prodId);
        if (prod == null) {
            throw new BusinessException("商品不存在");
        }
        ProdVO prodVO = new ProdVO();
        BeanUtil.copyProperties(prod, prodVO, "deliveryMode");
        // 将JSON字符串转换为DeliveryModeVO对象
        DeliveryModeVO deliveryModeVO = JSON.parseObject((String) prod.getDeliveryMode(), DeliveryModeVO.class);
        prodVO.setDeliveryMode(deliveryModeVO);
        // 获取商品关联的活动ID列表（状态为正常的）
        List<ProdTagReference> prodTagReferences = prodTagReferenceMapper.selectList(
                new LambdaQueryWrapper<ProdTagReference>()
                        .eq(ProdTagReference::getStatus, 1)
                        .eq(ProdTagReference::getProdId, prod.getProdId())
        );
        prodVO.setTagList(new ArrayList<>(0));
        if (!CollectionUtils.isEmpty(prodTagReferences)) {
            prodVO.setTagList(prodTagReferences.stream().map(ProdTagReference::getTagId).toList());
        }
        // 获取商品关联的SKU信息（状态为启用的）
        List<Sku> skus = skuMapper.selectList(
                new LambdaQueryWrapper<Sku>()
                        .eq(Sku::getStatus, 1)
                        .eq(Sku::getProdId, prod.getProdId())
        );
        prodVO.setSkuList(skus.stream().map(sku -> {
            SkuVO vo = new SkuVO();
            BeanUtil.copyProperties(sku, vo);
            return vo;
        }).toList());
        return prodVO;
    }

    @Override
    @CacheEvict(key = "#prodUpdateDTO.prodId")
    @Transactional(rollbackFor = Throwable.class)
    public boolean update(ProdUpdateDTO prodUpdateDTO) {
        Long shopId = AuthUtil.getShopId();
        if (shopId == null) {
            throw new BusinessException("请先关联店铺后操作");
        }
        Prod oldData = baseMapper.selectById(prodUpdateDTO.getProdId());
        // 1. 同店铺下的商品名不能重复
        if (prodUpdateDTO.getProdName() != null
                && !prodUpdateDTO.getProdName().equals(oldData.getProdName())
                && existsProdName(shopId, prodUpdateDTO.getProdName())) {
            throw new BusinessException("商品【" + prodUpdateDTO.getProdName() + "】已存在");
        }
        // 2. 向商品表中更新数据
        Prod updateProd = new Prod();
        BeanUtil.copyProperties(prodUpdateDTO, updateProd);
        if (prodUpdateDTO.getDeliveryModeVo() != null) {
            updateProd.setDeliveryMode(JSON.toJSONString(prodUpdateDTO.getDeliveryModeVo()));
        }
        updateProd.setUpdateTime(new Date());
        int row = 0;
        row += baseMapper.updateById(updateProd);

        // 3. 商品活动为null时不更新反之采用先删后加
        if (prodUpdateDTO.getTagList() != null) {
            row += prodTagReferenceMapper.delete(
                    new LambdaQueryWrapper<ProdTagReference>()
                            .eq(ProdTagReference::getProdId, prodUpdateDTO.getProdId())
            );
            if (!prodUpdateDTO.getTagList().isEmpty()) {
                row += prodTagReferenceMapper.batchInsert(shopId, prodUpdateDTO.getTagList(), prodUpdateDTO.getProdId(), 1, new Date());
            }
        }

        // 4. 更新SKU TODO: 批量更新
        if (prodUpdateDTO.getSkuList() != null
                && !CollectionUtils.isEmpty(prodUpdateDTO.getSkuList())) {
            List<Sku> skuList = prodUpdateDTO.getSkuList().stream().map(skuUpdateDTO -> {
                Sku sku = new Sku();
                BeanUtil.copyProperties(skuUpdateDTO, sku);
                sku.setUpdateTime(new Date());
                return sku;
            }).toList();
            for (Sku skuSaveData : skuList) {
                row += skuMapper.updateById(skuSaveData);
            }
        }

        // TODO：5. 配送相关

        log.debug("214:ProdServiceImpl.update():row:{}", row);
        return row > 0;
    }

    @Override
    @Cacheable(key = "#prodId")
    public ProdVO getProdAndSkuInfoById(Long prodId) {
        Prod prod = getById(prodId);
        if (prod == null) {
            throw new BusinessException("商品不存在");
        }
        List<Sku> skuList = skuMapper.selectList(
                new LambdaQueryWrapper<Sku>()
                        .eq(Sku::getStatus, 1)
                        .eq(Sku::getProdId, prod.getProdId())
        );
        ProdVO prodVO = new ProdVO();
        BeanUtil.copyProperties(prod, prodVO, "deliveryMode");
        prodVO.setSkuList(skuList.stream().map(sku -> {
            SkuVO vo = new SkuVO();
            BeanUtil.copyProperties(sku, vo);
            return vo;
        }).toList());
        return prodVO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public boolean updateStock(StockUpdateDTO stockUpdateDTO) {
        // 更新产品表
        stockUpdateDTO.getProdStockUpdateDTOList().forEach(prod -> {
            int row = baseMapper.updateStock(prod.getProdId(), prod.getCount());
            if (row <= 0) {
                throw new BusinessException("更新产品库存失败，产品ID：" + prod.getProdId());
            }
        });
        // 更新产品SKU表
        stockUpdateDTO.getProdSkuStockUpdateDTOList().forEach(sku -> {
            int row = skuMapper.updateStock(sku.getSkuId(), sku.getCount());
            if (row <= 0) {
                throw new BusinessException("更新SKU库存失败，SKU ID：" + sku.getSkuId());
            }
        });
        return true;
    }
}




